Fortran: Modeling Services as Derived Types
We’ve seen how to define a derived type to represent a point in 2D space. We were able to add a type-bound procedure to it, and finally to make its components private and define a custom constructor for it.
In essence there are two categories of derived types:
- Derived types that hold some data. Their type-bound procedures are solely dealing with this data, and may produce valuable information with it. The point is an example of such a derived type: we can use its data to make geometrical calculations, or we can combine it together with other points into lines, polygons, etc. This all happens in memory. In typical business applications you would consider entities, value objects and data transfer objects (DTOs) to be in this first category.
- Derived types that can perform some task that deals with things external to the application, like a file, the terminal, a network connection, etc. Such a type doesn’t hold data inside. It is able to fetch data, or send/store data. In business applications such a type is often called a service.
In object-oriented programming, service types usually offer an abstraction. This allows the client to decouple from its specific implementation details. For example, take a logger service; it’s often beneficial for the user that they don’t have to be concerned about where the logs are written to (file, screen, log aggregation server, etc.). The user only wants to call a simple log()
function to log something to whatever has been configured at some higher level. Introducing an logger abstraction will take a few posts from here, but it’s good to know that service abstraction is the goal.
By Matthias Noback
read moreFortran: Private Data Components and Custom constructors
In the previous post we have worked on the point_t
derived type, turning the module procedure distance
into a type-bound procedure:
module geometry
! ...
type :: point_t
real :: x
real :: y
contains
procedure :: distance => point_distance
end type point_t
contains
pure function point_distance(point_1, point_2) result(the_distance)
class(point_t), intent(in) :: point_1
! ...
end function point_distance
end module geometry
Private data components
Type-bound procedures can help us tie relevant behaviors (procedures) to derived types. It also allows us to let the derived type keep its data to itself. This is often called data hiding, or encapsulation of state. Nothing outside the module where the derived type is defined will have (read or write) access to its data components. This can be accomplished by adding the attribute private
to each data component:
By Matthias Noback
read moreFortran: Type-bound Procedures
In the previous post we defined a derived type point_t
with real
data components x
and y
, to represent a point in 2D space. We also wrote a function to calculate the distance between two such points:
module geometry
implicit none(type, external)
private
public :: point_t
public :: distance
type :: point_t
real :: x
real :: y
end type point_t
contains
pure function distance(point_1, point_2) result(the_distance)
type(point_t), intent(in) :: point_1
type(point_t), intent(in) :: point_2
real :: the_distance
the_distance = sqrt((point_2%x - point_1%x)**2 + &
(point_2%y - point_1%y)**2)
end function distance
end module geometry
This allowed us to pass point_t
instances as function arguments to distance
, in another module or in the program
:
By Matthias Noback
read moreFortran: Derived Types
We’ve seen types and variables and functions and subroutines. Now we can get to the next level and combine both variables and procedures in a so-called derived type.
Declaring a derived type and its data components
Object-oriented programming languages have classes. It took me some time to understand that classes can be seen as “extensions of the type system”. There are often primitive types like strings, integers, etc. and we can group them as properties of a class. Thereby, the class becomes some kind of advanced, composite type.
By Matthias Noback
read more